package com.aiwiown.snackmq.broker;

import com.aiwiown.snackmq.broker.config.BrokerConfig;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * 单独启动 Broker 集群节点 (localhost:9878)。
 * <p>
 * 运行此 main 方法将启动一个独立的 Broker 节点。
 * 该节点被配置为 "snackmq-manual-cluster" 集群的一部分。
 * 你需要分别运行 Cluster9876 和 Cluster9880 来组成一个完整的三节点集群。
 * </p>
 */
public class Cluster9878 {

    private static final String HOST = "localhost";
    private static final String BASE_DATA_PATH = "data/manual-cluster";
    private static final String RAFT_GROUP_ID = "snackmq-manual-cluster";

    // --- 本节点特定配置 ---
    private static final int SERVER_PORT = 9878;
    private static final int RAFT_PORT = 9879;
    private static final int BROKER_INDEX = 1; // 用于区分数据目录，与 ClusterRunner 保持一致

    // --- 完整集群信息 (Raft选举需要) ---
    private static final String RAFT_INITIAL_CONF = "localhost:9877,localhost:9879,localhost:9881";
    private static final Map<String, Integer> RAFT_TO_BUSINESS_PORT_MAP = new HashMap<>();

    static {
        RAFT_TO_BUSINESS_PORT_MAP.put("localhost:9877", 9876);
        RAFT_TO_BUSINESS_PORT_MAP.put("localhost:9879", 9878);
        RAFT_TO_BUSINESS_PORT_MAP.put("localhost:9881", 9880);
    }

    public static void main(String[] args) throws Exception {
        System.out.println("--- 准备启动 SnackMQ Broker 节点: " + HOST + ":" + SERVER_PORT + " ---");

        // 1. 清理该节点旧的数据目录 (可选，确保全新启动)
//        File dataDir = new File(BASE_DATA_PATH + "/broker-" + BROKER_INDEX);
//        if (dataDir.exists()) {
//            System.out.println("清理旧的数据目录: " + dataDir.getAbsolutePath());
//            deleteDirectory(dataDir);
//        }

        // 2. 创建 Broker 配置
        BrokerConfig config = new BrokerConfig();
        config.setHost(HOST);
        config.setServerPort(SERVER_PORT);
        config.setRaftPort(RAFT_PORT);

        config.setStorePath(BASE_DATA_PATH + "/broker-" + BROKER_INDEX + "/store");
        config.setRaftDataPath(BASE_DATA_PATH + "/broker-" + BROKER_INDEX + "/raft");
        config.setRaftElectionTimeoutMs(3000);
        config.setRaftGroupId(RAFT_GROUP_ID);

        // 启用认证，与 ClusterRunner 和测试保持一致
        config.setAuthEnabled(true);
        config.setDefaultAdminUser("admin");
        config.setDefaultAdminPassword("admin");

        // 3. 设置集群的 Raft 初始配置
        config.setRaftInitialConf(RAFT_INITIAL_CONF);
        config.setRaftAddressToBusinessPortMap(RAFT_TO_BUSINESS_PORT_MAP);

        //基于索引恢复
        config.setForceFullLogRecovery(true);

        // 4. 创建并启动 Broker 实例
        BrokerServer broker = new BrokerServer(config);
        System.out.println("--- 开始启动 Broker 节点... ---");
        try {
            broker.start();
            System.out.println("\n=======================================================");
            System.out.println(" Broker 已在端口 " + broker.getBrokerConfig().getServerPort() + " (Raft: " + broker.getBrokerConfig().getRaftPort() + ") 启动。");
            System.out.println(" 该节点是集群 '" + RAFT_GROUP_ID + "' 的一部分。");
            System.out.println(" 请依次启动其他集群节点 (Cluster9876, Cluster9880)。");
            System.out.println(" 按 Ctrl+C 停止该节点。");
            System.out.println("=======================================================\n");
        } catch (Exception e) {
            System.err.println("Broker 启动失败: " + e.getMessage());
            e.printStackTrace();
            return;
        }

        // 5. 阻塞主线程，使 Broker 持续运行
        new CountDownLatch(1).await();
    }

    private static void deleteDirectory(File directory) {
        if (!directory.exists()) {
            return;
        }
        File[] allContents = directory.listFiles();
        if (allContents != null) {
            for (File file : allContents) {
                deleteDirectory(file);
            }
        }
        directory.delete();
    }
}